package com.dartfar.workflow.service;

import java.util.List;

import javax.annotation.Resource;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.jbpm.api.TaskQuery;
import org.jbpm.api.TaskService;
import org.jbpm.api.task.Participation;
import org.jbpm.api.task.Task;
import org.springframework.stereotype.Component;

import com.dartfar.base.dao.DaoUtil;
import com.dartfar.base.model.BaseEntity;
import com.dartfar.base.model.Person;
import com.dartfar.util.EntityUtils;
import com.dartfar.util.StringUtils;
import com.dartfar.workflow.constant.StringVeriable;
import com.dartfar.workflow.constant.WorkflowButtons;
import com.dartfar.workflow.constant.WorkflowCaleType;
import com.dartfar.workflow.constant.WorkflowDeployVar;
import com.dartfar.workflow.constant.WorkflowStatusVar;
import com.dartfar.workflow.model.WorkflowDeployTask;
import com.dartfar.workflow.model.WorkflowDeployment;
import com.dartfar.workflow.model.WorkflowProcessFunMount;
import com.dartfar.workflow.model.WorkflowTaskFunMount;
import com.dartfar.workflow.vo.WorkflowButtonsVo;
import com.dartfar.workflow.vo.WorkflowPermissionVo;

@Component("workflowPermissionService")
public class WorkflowPermissionServiceImpl implements WorkflowPermissionService {

	static Logger logger = Logger.getLogger(WorkflowPermissionServiceImpl.class);
	
	@Resource
	private DaoUtil<BaseEntity> baseEntityDaoUtil;
	@Resource
	private DaoUtil<WorkflowProcessFunMount> workflowProcessFunMountDaoUtil;
	@Resource
	private DaoUtil<WorkflowDeployment> workflowDeploymentDaoUtil;
	@Resource
	private DaoUtil<WorkflowTaskFunMount> workflowTaskFunMountDaoUtil;
	@Resource
	private TaskService taskService;
	
	@Override
	public void loadWorkflowPermissionData(Person person, String modelName,String modelIdName, int id, JSONObject returnObj) {
		// TODO Auto-generated method stub
		//WorkflowProcessFunMount
		Class clazz = null;
		try {
			clazz = Class.forName(modelName);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			logger.error("实体名称有误.");
		}
		
		WorkflowPermissionVo<WorkflowButtonsVo> wpVos = new WorkflowPermissionVo<WorkflowButtonsVo>(); 
		logger.info("ID: " + id);
		BaseEntity entity = (BaseEntity) baseEntityDaoUtil.get(id, clazz);
		//当前登录人
		//String curPersonName = person.getName();
		String curPersonId = String.valueOf(person.getPersonId());
		logger.info("curPersonId: " + curPersonId);
		String processInstanceId = entity.getProcessInstanceId();
		logger.info("processInstanceId: " + processInstanceId);
		String processDefinitionId = entity.getProcessDefinitionId();
		logger.info("processDefinitionId: " + processDefinitionId);
		String workflowStauts = entity.getWorkflowStatus();
		logger.info("workflowStauts: " + workflowStauts);
		//String createPerson = entity.getPerson();
		String createPersonId = String.valueOf(entity.getPersonId());
		logger.info("createPersonId: " + createPersonId);
		
		//List<WorkflowButtonsVo> wbVos = new ArrayList<WorkflowButtonsVo>();
		//如果流程未启动
		if(!StringUtils.isNotEmpty(processInstanceId) || !StringUtils.isNotEmpty(processDefinitionId) || (!StringUtils.isNotEmpty(workflowStauts) && !workflowStauts.equalsIgnoreCase(WorkflowStatusVar.NO_STATUS))){
			
			//如果当前登录人不是创建记录人则没有权限启动
			if(!curPersonId.equalsIgnoreCase(createPersonId)){
				logger.info("没有权限。");
				return;
			}

			String hql = "from WorkflowProcessFunMount w where w.modelName = ? and w.modelIdName = ? and mountStatus = ?";
			List<WorkflowProcessFunMount> workflowProcessFunMounts = (List<WorkflowProcessFunMount>) workflowProcessFunMountDaoUtil.getList(hql, new Object[]{modelName, modelIdName, WorkflowStatusVar.MOUNTSTATUS_YES}, new Type[]{new StringType(), new StringType(), new StringType()});
			if(!EntityUtils.isNotNull(workflowProcessFunMounts) || workflowProcessFunMounts.size() <= 0){
				return;
			}
			
			String processNames = "";
			String processIds = "";
			
			for(WorkflowProcessFunMount process : workflowProcessFunMounts){
				processNames += process.getProcessName() + ",";
				processIds += process.getId() + ",";
			}
			logger.info("processNames: " + processNames);
			logger.info("processIds: " + processIds);
			if(StringUtils.isNotEmpty(processNames) && StringUtils.isNotEmpty(processIds)){
				processNames = processNames.substring(0, processNames.length()-1);
				processIds = processIds.substring(0, processIds.length()-1);
				returnObj.put("processFunMountIds", processIds);
				returnObj.put("processFunMountNames", processNames);
			}
			//设置启动按钮
			returnObj.put("buttons", WorkflowButtons.BTN_START);
			return;
		}
		
		TaskQuery tq = taskService.createTaskQuery();
		tq.processDefinitionId(processDefinitionId);
		tq.processInstanceId(processInstanceId);
		List<Task> tasks = tq.list();
		if(EntityUtils.isNotNull(tasks) && tasks.size() > 0){
			for(Task task:tasks){
				returnObj.put("taskId", task.getId());
				/*是否执行人*/
				boolean isAssignee = false;
				/*是否可收回人*/
				boolean isWithdraw = false;
				/*是否拥有人*/
				boolean isOwner = false;
				/*是否候选人*/
				boolean isCandidate = false;
				/*是否是否可回退*/
				boolean rollbackable = true;
				/*是否是否可收回*/
				boolean withdrawable = true;
				String piOwner = String.valueOf(taskService.getVariable(task.getId(), WorkflowDeployVar.PI_OWNER));
				logger.info("piOwner : " + piOwner);
				String isRollbackable = (String) taskService.getVariable(task.getId(), WorkflowDeployVar.ROLLBACKABLE);
				logger.info("isRollbackable : " + isRollbackable);
				String isWithdrawable = (String) taskService.getVariable(task.getId(), WorkflowDeployVar.WITHDRAWABLE);
				logger.info("isWithdrawable : " + isWithdrawable);
//				String rollBackUser=(String) taskService.getVariable(task.getId(), WfVarDeploy.ROLLBACKUSER);
				//拿到回收人是谁
				String withdRawPerson = String.valueOf(taskService.getVariable(task.getId(), WorkflowDeployVar.WITHDRAWUSER));
				
				if(!StringVeriable.STR_TRUE.equalsIgnoreCase(isRollbackable)){
					rollbackable=false;
				}
				if(!StringVeriable.STR_TRUE.equalsIgnoreCase(isWithdrawable)){
					withdrawable=false;
				}
				//得到功能挂接对象
				WorkflowTaskFunMount taskFunMount = findWorkflowTaskFunMount(processDefinitionId, task.getName());
				
				if(!returnObj.containsKey("ableButtons")){
					returnObj.put("ableButtons", taskFunMount.getAbleButtons());
				}
				if(!returnObj.containsKey("ableFields")){					
					returnObj.put("ableFields", taskFunMount.getAbleFileds());
				}
				
				if(!StringUtils.isNotEmpty(task.getAssignee())) {
					//找到候选人
					List<Participation> taskParticipations = taskService.getTaskParticipations(task.getId());
					if(null != taskParticipations) {
						for(Participation participation : taskParticipations) {
							//if(Participation.CANDIDATE.equalsIgnoreCase(participation.getType()) && curPersonId.equalsIgnoreCase(participation.getUserId())) {
							if(Participation.CANDIDATE.equalsIgnoreCase(participation.getType()) && curPersonId.equalsIgnoreCase(participation.getUserId())) {
							// 当前登录人是此任务的候选人之一
								isCandidate = true;
								break; // 判断成功，中断循环
							}
						}
					}
				}
				//如果是候选人。 直接给定处理任务节点
				if(isCandidate) {
					returnObj.put("buttons", new String[]{WorkflowButtons.BTN_TAKETASK});
					returnObj.put("WF_STATUS", WorkflowStatusVar.WAIT_STATUS);
					return;
				}
				//如果是执行人
				logger.info("curPersonId: " + curPersonId);
				logger.info("getAssignee: " + task.getAssignee());
				if(curPersonId.equalsIgnoreCase(task.getAssignee())){
					isAssignee = true;
				}
				//判断是否可取回人
				if(curPersonId.equalsIgnoreCase(withdRawPerson)){
					isWithdraw = true;
				}
				//是否流程启动人
				if(piOwner.equalsIgnoreCase(curPersonId)){
					isOwner = true;
				}
				//如果是执行人
				if(isAssignee) {
					logger.info("isAssignee: " + isAssignee);
					String taskName = task.getName();
					WorkflowDeployTask depTask = findWorkflowDeployTask(processDefinitionId, taskName);
					if(EntityUtils.isNotNull(depTask)){
						String assigneIds = depTask.getAssignees();
						logger.info("assigneIds: " + assigneIds);
						String assignType = depTask.getAssigneType();
						logger.info("assignTypeIds: " + assignType);
						String roleIds = depTask.getAssigneRoles();
						logger.info("roleIds: " + roleIds);
						
						//如果委托类型为归档
						if(assignType.equalsIgnoreCase(WorkflowCaleType.CALE_END)){
							//设置归档按钮
							returnObj.put("buttons", new String[]{WorkflowButtons.BTN_ROLLBACK, WorkflowButtons.BTN_END});
						}else{
							if(rollbackable){
								//设置回退按钮，发送按钮
								returnObj.put("buttons", new String[]{WorkflowButtons.BTN_ROLLBACK, WorkflowButtons.BTN_SUBMIT});
							}else{
								//设置发送按钮
								returnObj.put("buttons", new String[]{WorkflowButtons.BTN_SUBMIT});							
							}
						}
						returnObj.put("assigneType", assignType);
						returnObj.put("assignes", assigneIds);
						returnObj.put("roles", roleIds);
					}
					logger.info("如果是执行人returnObj: " + returnObj.toString());
				}
				//只是一个回收人操作
				if(isWithdraw) {
					// 当前登录用户是任务的可回收人
					if(withdrawable) {
						//取回
						returnObj.put("buttons", new String[] {WorkflowButtons.BTN_TAKEBACK});
					}			
					logger.info("回收人操作returnObj: " + returnObj.toString());
				}
				if(isAssignee && isWithdraw) {
					// 当前登录用户即是任务的可回收人又是任务的执行人（任务启动时）
					if(withdrawable) {
						returnObj.put("buttons", new String[] {WorkflowButtons.BTN_TAKEBACK, WorkflowButtons.BTN_SUBMIT});
					} else {
						returnObj.put("buttons", new String[] {WorkflowButtons.BTN_SUBMIT});
					}
					logger.info("当前登录用户即是任务的可回收人又是任务的执行人returnObj: " + returnObj.toString());
				}
				//如果任务提交出去
				if(isOwner && isWithdraw) {
					if(withdrawable) {
						returnObj.put("buttons", new String[] {WorkflowButtons.BTN_TAKEBACK});
					}
					logger.info("如果任务提交出去returnObj: " + returnObj.toString());
				}
				//这代表任务启动后， 他做了提交后被回退，又提交，又收回。
				if(isOwner && isWithdraw && isAssignee) {
					// 退来退去退到任务创建人
					returnObj.put("buttons", new String[] {WorkflowButtons.BTN_CALLPROCESS, WorkflowButtons.BTN_SUBMIT});
					logger.info("重复发送回退returnObj: " + returnObj.toString());
				}
				//如果已经有按钮则返回，主要用户fork分支时候出现两个活动节点
				if(returnObj.containsKey("buttons")) {
					return;
				}
				logger.info("returnObj: " + returnObj.toString());
			}} else { 
				//结束任务
				//wpVos.setStatus(WorkflowStatusVar.END_STATUS);
				returnObj.put("WF_STATUS", WorkflowStatusVar.END_STATUS);
				return;
			}
		return;
	}

	/**
	 * 查询任务部署对象
	 * @param pdid
	 * @param taskName
	 * @return
	 */
	@Override
	public WorkflowDeployTask findWorkflowDeployTask(String pdid, String taskName){
		WorkflowDeployment deployment = (WorkflowDeployment) workflowDeploymentDaoUtil.get("from WorkflowDeployment w where w.processDefinitionId = '"+pdid+"'");
			//(WfDeployement) pcManagerTemplate.getEntityByHql(" from WfDeployement where processDefinitionId='"+pdid+"'");
		WorkflowDeployTask deployTask = new WorkflowDeployTask();
		if(EntityUtils.isNotNull(deployment)){
			List<WorkflowDeployTask> tasks = deployment.getWorkflowDeployTasks();
			for(WorkflowDeployTask task : tasks){
				if(task.getTaskName().equalsIgnoreCase(taskName)){
					deployTask=task;
					break;
				}
			}
		}else{
			logger.info("没有找到部署实体。");
			//System.out.println("没有找到部署实体");
		}
		return deployTask;
	}
	
	/**
	 * 查找任务挂接实体
	 * @param deployId
	 * @param taskName
	 * @return
	 */
	@Override
	public WorkflowTaskFunMount findWorkflowTaskFunMount(String deployId, String taskName){
		WorkflowTaskFunMount taskFunMount = (WorkflowTaskFunMount) workflowTaskFunMountDaoUtil.get("from WorkflowTaskFunMount w where w.processDefinitionId='"+deployId+"' and w.taskNodeName='"+taskName+"'");
		if(EntityUtils.isNotNull(taskFunMount)){
			return taskFunMount;
		}else{
			return new WorkflowTaskFunMount();
		}
	}
	
	@Override
	public WorkflowDeployment findWorkflowDeployment(String modelName,String modelId) {
		// TODO Auto-generated method stub
		Class clazz=null;
		try {
			clazz=Class.forName(modelName);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			logger.error(modelName + " 实例化失败.");
			e.printStackTrace();
			return null;
		}
		BaseEntity entity = baseEntityDaoUtil.get(Integer.valueOf(modelId).intValue(), clazz);
		if(EntityUtils.isNotNull(entity)){
			WorkflowDeployment deploy = (WorkflowDeployment) workflowDeploymentDaoUtil.get("from WfDeployement w where w.processDefinitionId='" + entity.getProcessDefinitionId() + "'");
			return deploy;
		}else{
			return null;
		}
		
	}
}
